package util

import (
	"flag"
	"os/exec"
	"runtime"
	"testing"
	"time"

	"file_explorer/common/consts"
)

var env string

func init() {
	envPointer := flag.String("env", consts.EnvProduct, "env")
	testing.Init()
	flag.Parse()

	env = *envPointer
	if InStrArray(env, []string{consts.EnvProduct, consts.EnvDev}) < 0 {
		env = consts.EnvDev
	}
}

func IsDevEnv() bool {
	return env == consts.EnvDev
}

func IsOsWindows() bool {
	return runtime.GOOS == "windows"
}

func IsOsMac() bool {
	return runtime.GOOS == "darwin"
}

func RunCommand(name string, args ...string) error {
	if IsOsWindows() {
		args = append([]string{"/C", name}, args...)
		name = "cmd"
	}
	cmd := exec.Command(name, args...)
	err := cmd.Run()
	if err != nil {
		return err
	}
	return nil
}

var (
	sn            int64
	lastTimeStamp int64
)

func GetSnowflakeId() int64 {
	curTimeStamp := time.Now().UnixNano() / 1000000

	// 同一毫秒
	if curTimeStamp == lastTimeStamp {
		sn++
		// 序列号占 12 位,十进制范围是 [ 0, 4095 ]
		if sn > 4095 {
			time.Sleep(time.Millisecond)
			curTimeStamp = time.Now().UnixNano() / 1000000
			lastTimeStamp = curTimeStamp
			sn = 0
		}

		// 取 64 位的二进制数 0000000000 0000000000 0000000000 0001111111111 1111111111 1111111111  1 ( 这里共 41 个 1 )和时间戳进行并操作
		// 并结果( 右数 )第 42 位必然是 0,  低 41 位也就是时间戳的低 41 位
		rightBinValue := curTimeStamp & 0x1FFFFFFFFFF
		// 机器 id 占用10位空间,序列号占用12位空间,所以左移 22 位; 经过上面的并操作,左移后的第 1 位,必然是 0
		rightBinValue <<= 22
		id := rightBinValue | sn
		return id
	}

	if curTimeStamp > lastTimeStamp {
		sn = 0
		lastTimeStamp = curTimeStamp
		// 取 64 位的二进制数 0000000000 0000000000 0000000000 0001111111111 1111111111 1111111111  1 ( 这里共 41 个 1 )和时间戳进行并操作
		// 并结果( 右数 )第 42 位必然是 0,  低 41 位也就是时间戳的低 41 位
		rightBinValue := curTimeStamp & 0x1FFFFFFFFFF
		// 机器 id 占用10位空间,序列号占用12位空间,所以左移 22 位; 经过上面的并操作,左移后的第 1 位,必然是 0
		rightBinValue <<= 22
		id := rightBinValue | sn
		return id
	}

	if curTimeStamp < lastTimeStamp {
		return 0
	}

	return 0
}
